<?php
/**
 * 图片输出处理
 * <br>
 * 在main.php中挂载组件：
 * <pre>
 * 'components' => array(
 *  ...
 *  'img' => array(
 *   'class' => 'lib.components.CImageOutput',
 *   // 配置文件
 *   'configFile' => 'application.comfig.image',
 *  ),
 *  ...
 * );
 * </pre>
 * 这个文件的alias路径将被设置给configFile属性，并且在
 * 初始化的时候将内容赋值给_config属性，文件内容如下：
 * <pre>
 * // @file: application.config.image
 * return array(
 *  // 配置的名称，任意字符
 *  'member.avatar' => array(
 *   // 图片的URL根路径
 *   'baseUrl' => Yii::app()->baseUrl . '/uploaded',
 *   // 图片的文件根路径
 *   'basePath' => dirname(Yii::app()->basePath) . '/uploaded',
 *   // 图片宽度
 *   'width' => '150',
 *   // 图片高度
 *   'height' => '150',
 *   // 图片未找到
 *   'notFound' => Yii::app()->baseUrl . '/uploaded/img-not-found.jpg',
 *   // 图片未上传
 *   'notUpload' => Yii::app()->baseUrl . '/uploaded/img-not-upload.jpg',
 *  )
 * );
 * </pre>
 * 配置中可以有多个节点，在使用时，必须先用config方法切换配置：如下
 * <pre>
 * // 切换到member.avatar配置
 * Yii::app()->img->config('member.avatar');
 * // 输出图片
 * echo Yii::app()->img->image($model->avatar);
 * // 也可以使用连贯操作
 * echo Yii::app()->img->config('member.avatar')->image($model->avatar);
 * </pre>
 * @author yangdongqi <yangdongqi@hayzone.com>
 * @package lib.components
 */
class CImageOutput2 extends CComponent {
	
	/**
	 * 配置alias路径
	 * <br>
	 * 必须是一个标准的PHP文件
	 * e.g. application.config.image
	 * @var string
	 */
	public $configFile = '';
	
	protected $_config = array();
	protected $_currentConfig = array();
	
	public function config($name) {
		$config = $this->_config[$name];
		$this->_currentConfig = $config;
		return $this;
	}
	
	public function getBaseUrl() {
		return $this->_currentConfig['baseUrl'];
	}
	
	public function getBasePath() {
		return $this->_currentConfig['basePath'];
	}
	
	public function init() {
		$file = Yii::getPathOfAlias($this->configFile) . '.php';
		$this->_config = require $file;
	}
	
	/**
	 * 获取当前配置项
	 * @param string $name 配置项的key name
	 * @return mixed
	 */
	public function getConfig($name) {
		return isset($this->_currentConfig[$name]) ? $this->_currentConfig[$name] : null;
		return $this->_currentConfig[$name];
	}
	
	/**
	 * 返回图片的url
	 * @param string $src
	 * @param int $width
	 * @param int $height
	 * @param boolean $cut
	 * @return string
	 */
	public function url($src, $width = null, $height = null, $cut = true) {
		
		if(!$src) {
			return $this->getConfig('notUpload');
		}
		$srcPath = $this->getBasePath() . '/' . $src;

		if(!is_file($srcPath)) {
			return $this->getConfig('notFound');
		}
		
		$width = $width ? $width : $this->getConfig('width');
		$height = $height ? $height : $this->getConfig('height');
		
		$pi = pathinfo($src);
		if(!$width || !$height) return $this->getBaseUrl() . $src;
		
		$pi = pathinfo($src);
		$newFile = $pi['dirname'].'/'.$pi['filename']."_{$width}x{$height}.".$pi['extension'];
		
		$newPath = $this->getBasePath() . '/' . $newFile;
		$newUrl = $this->getBaseUrl() . '/' . $newFile;
		
		$pi = pathinfo($srcPath);
		if(!is_file($newPath)) {
			$image = new CImageResizer($srcPath, $width, $height, $cut);
			$image->run($newPath);
		}
		
		if(!is_file($newPath)) {
			return $this->getBaseUrl().$src;
		}
		
		return $newUrl;
	}
	
	/**
	 * 返回物理路径
	 * @param string $src
	 * @return boolean
	 */
	public function getSrcPath($src) {
		if(!$src) return false;
		$srcPath = $this->getBasePath() . '/' . $src;
		return is_file($srcPath);
	}
	
	/**
	 * 返回CHtml::image
	 * @param string $src
	 * @param string $alt
	 * @param array $htmlOptions
	 * @param array $params 调用CImageOutput::url所使用的参数
	 * @return string
	 */
	public function out($src, $htmlOptions = array(), $params = array()) {
		Yii::import('lib.helpers.utils.CUtilHelper');
		
		CUtilHelper::arr()->fillKeys($params, array('width', 'height', 'cut'));
		$url = $this->url($src, $params['width'], $params['height'], $params['cut']);
		
		$params['width'] = $params['width'] ? $params['width'] : $this->getConfig('width');
		$params['height'] = $params['height'] ? $params['height'] : $this->getConfig('height');
		
		$htmlOptions['height'] = isset($htmlOptions['height']) ? $htmlOptions['height'] : $params['height'];
		$htmlOptions['width'] = isset($htmlOptions['width']) ? $htmlOptions['width'] : $params['width'];
		$htmlOptions['class'] = isset($htmlOptions['class']) ? $htmlOptions['class'] : 'cimg_default';
		return CHtml::image($url, '', $htmlOptions);
	}
}


/**
 * 缩略图
 * @author http://www.oschina.net/code/snippet_5189_2491
 * @package lib.components
 */
class CImageResizer
{
    //图片类型
    var $type;
    //实际宽度
    var $width;
    //实际高度
    var $height;
    //改变后的宽度
    var $resize_width;
    //改变后的高度
    var $resize_height;
    //是否裁图
    var $cut;
    //源图象
    var $srcimg;
    //目标图象地址
    var $dstimg;
    //临时创建的图象
    var $im;

    function CImageResizer($img, $wid, $hei,$c) {
        $this->srcimg = $img;
        $this->resize_width = $wid;
        $this->resize_height = $hei;
        $this->cut = $c;
    }
    
    public function run($dstpath) {
    	//图片的类型
		$this->type = strtolower(substr(strrchr($this->srcimg,"."),1));

        //初始化图象
        $this->initi_img();
        if(!$this->im) return false;
        
		//目标图象地址
		$this->dstimg = $dstpath;
		
        $this->width = imagesx($this->im);
        $this->height = imagesy($this->im);
        
		//生成图象
        $this->newimg();
        
		ImageDestroy($this->im);
        return true;
    }
    
    function newimg() {

        $ratio = max($this->width / $this->resize_width, $this->height / $this->resize_height);
		$newWidth = floor($this->width / $ratio);
		$newHeight = floor($this->height / $ratio);
      
		$newimg = imagecreatetruecolor($newWidth, $newHeight);
		imagecopyresampled(
			$newimg, $this->im, 
			0, 0, 0, 0, 
			$newWidth, $newHeight, 
			$this->width, $this->height
		);
		ImageJpeg($newimg, $this->dstimg, 100);
		
    }

    //初始化图象
    function initi_img() {
		switch($this->type) {
			case 'jpg':
			case 'jpeg':
				return $this->im = @imagecreatefromjpeg($this->srcimg);
			case 'gif':
				return $this->im = @imagecreatefromgif($this->srcimg);
			case 'png':
				return $this->im = @imagecreatefrompng($this->srcimg);
		}
		return false;
    }
}
?>